package com.dsideal.scratch;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.Set;
import java.util.zip.GZIPInputStream;

import org.apache.commons.lang.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.w3c.css.sac.InputSource;
import org.w3c.dom.css.CSSFontFaceRule;
import org.w3c.dom.css.CSSImportRule;
import org.w3c.dom.css.CSSRule;
import org.w3c.dom.css.CSSRuleList;
import org.w3c.dom.css.CSSStyleDeclaration;
import org.w3c.dom.css.CSSStyleRule;
import org.w3c.dom.css.CSSStyleSheet;

import com.steadystate.css.parser.CSSOMParser;
import com.steadystate.css.parser.SACParserCSS3;

public class ScratchUtil {

	/**
	 * http://www.zi-han.net/theme/hplus/index.html
	 * urlPrefix, http://www.zi-han.net/theme
	 * projectName, 相对目录，例如hplus, 其他文件都是相对这个目录开始
	 * rootHtml, 根入口, index.html
	 */
	private String urlPrefix;
	private String projectName;
	
	public ScratchUtil(String urlPrefix, String projectName) {
		this.urlPrefix = urlPrefix.endsWith("/")?urlPrefix.substring(0, urlPrefix.indexOf("/")):urlPrefix;
		this.projectName = projectName; //如果相对目录为空，则下载到项目根目录
	}
	
	public static void main(String[] args) throws IOException {
		//ScratchUtil su = new ScratchUtil("https://www.uetdsme.com", "");
		//su.start("/uetd/index.html", true);//rootHtml不能有相对目录，否则需要处理
		//su.downLoadFiles("", "index.html");
		
		ScratchUtil su = new ScratchUtil("http://www.jsdaima.com/Upload", "1474607770");
		su.start("index.html", false);
		
		
	}
	
	public void start(String rootHtml, boolean excludeHtml) throws IOException{
		if(!excludeHtml){
			downLoadHtml(rootHtml);
		}
		downLoadJs(projectName);
		downLoadCss(projectName);
		downLoadImg(projectName);
		downLoadCssImgFonts(projectName);
	}
	
	//递归下载html
	private Set<String> htmlSet = new HashSet<String>();
	public void downLoadHtml(String htmlHref) throws IOException{
		//1.判断本地是否已经存在文件, 不存在则先下载, 然后解析
		File hf = new File((this.projectName.length() > 0 ? (this.projectName + "/") : "") + htmlHref);
		if(!htmlSet.contains(hf.getPath())){
			//if(!hf.exists()){
				String filePath = hf.getParent()!=null?hf.getParent().replace("\\", "/"):"";
				String fileName = hf.getName();
				downLoadFiles(filePath, fileName);
				
				Document doc = Jsoup.parse(hf,"utf-8");
				//记住解析过的文件,下次就不解析了
				htmlSet.add(hf.getPath());
				System.out.println(hf.getPath());
				Elements atags = doc.getElementsByAttributeValueContaining("href", ".html");
				for(Element e : atags){
					String href = e.attr("href");
					if(href == null || "".equals(href)){
						continue;
					}
					if(href.indexOf("http://") != -1 || href.indexOf("https://") != -1){
						continue;
					}
					if(href.indexOf("?") != -1){
						href = href.substring(0, href.indexOf("?"));
					}
					if(href.indexOf("#") != -1){
						href = href.substring(0, href.indexOf("#"));
					}
					if("".equals(href)){
						continue;
					}
					if(htmlHref.equals(href)){
						continue;
					}
					int backCount = StringUtils.countMatches(href, "../");
					//if(backCount > 0){
					//	System.out.println(111);
					//}
					File rf = new File(htmlHref);;
					for(int i=0;i<backCount;i++){
						href = href.replace("../", "");
						if(rf != null){
							rf = rf.getParentFile();
						}
					}
					
					//href是“/”则是绝对路径, 没有则是相对路径
					if(href.startsWith("/")){
						//href = rf.getParent().replace("\\", "/");
					}else{
						if(rf.getParent() != null)
						href = rf.getParent().replace("\\", "/") + href;
					}
					
					downLoadHtml(href);
				}
			//}
		}
	}
	
	//递归本地html，下载js
	public void downLoadJs(String filePath) throws IOException{
		File file = new File(filePath);
		if(file.isDirectory()){
			for(File f : file.listFiles()){
				if(f.isDirectory()){
					downLoadJs(f.getPath());
				}else if(f.isFile() && f.getName().endsWith(".html")){
					Document doccss = Jsoup.parse(f,"utf-8");
					Elements elinks = doccss.getElementsByTag("script");
					for(Element elink : elinks){
						String jshref = elink.attr("src");
						if(jshref == null || "".equals(jshref)){
							continue;
						}
						if(jshref.indexOf("http://") != -1 || jshref.indexOf("https://") != -1){
							continue;
						}
						if(jshref.indexOf("?") != -1){
							jshref = jshref.substring(0, jshref.indexOf("?"));
						}
						if(jshref.indexOf("#") != -1){
							jshref = jshref.substring(0, jshref.indexOf("#"));
						}
						if("".equals(jshref)){
							continue;
						}
						int backCount = StringUtils.countMatches(jshref, "../");
						//if(backCount > 0){
						//	System.out.println(111);
						//}
						File rf = new File(f.getPath());
						for(int i=0;i<backCount;i++){
							jshref = jshref.replace("../", "");
							if(rf != null){
								rf = rf.getParentFile();
							}
						}
						if(rf.getParent() != null)
							jshref = rf.getParent().replace("\\", "/") + "/" + jshref;
						
						File jf = new File(jshref);
						String jfp = jf.getParent().replace("\\", "/");
						String jfn = jf.getName();
						downLoadFiles(jfp, jfn);
					}
				}
			}
		}else if(file.isFile()){
			//直接解析
		}
	}
	
	//递归本地html，下载css
	public void downLoadCss(String filePath) throws IOException{
		File file = new File(filePath);
		if(file.isDirectory()){
			for(File f : file.listFiles()){
				if(f.isDirectory()){
					downLoadCss(f.getPath());
				}else if(f.isFile() && f.getName().endsWith(".html")){
					Document doccss = Jsoup.parse(f,"utf-8");
					Elements elinks = doccss.getElementsByTag("link");
					for(Element elink : elinks){
						String rel = elink.attr("rel");
						String csshref = elink.attr("href");
						if(rel.equals("stylesheet") || rel.equals("shortcut icon")){
							if(csshref == null || "".equals(csshref)){
								continue;
							}
							if(csshref.indexOf("http://") != -1 || csshref.indexOf("https://") != -1){
								continue;
							}
							if(csshref.indexOf("?") != -1){
								csshref = csshref.substring(0, csshref.indexOf("?"));
							}
							if(csshref.indexOf("#") != -1){
								csshref = csshref.substring(0, csshref.indexOf("#"));
							}
							if("".equals(csshref)){
								continue;
							}
							int backCount = StringUtils.countMatches(csshref, "../");
							//if(backCount > 0){
							//	System.out.println(111);
							//}
							File rf = new File(f.getPath());
							for(int i=0;i<backCount;i++){
								csshref = csshref.replace("../", "");
								if(rf != null){
									rf = rf.getParentFile();
								}
							}
							if(rf.getParent() != null)
								csshref = rf.getParent().replace("\\", "/") + "/" + csshref;
							
							File cf = new File(csshref);
							String cfp = cf.getParent() != null ? cf.getParent().replace("\\", "/") : "";
							String cfn = cf.getName();
							downLoadFiles(cfp, cfn);
						}
					}
				}
			}
		}else if(file.isFile()){
			//直接解析
		}
	}
	
	//递归本地html，下载js
	public void downLoadImg(String filePath) throws IOException{
		File file = new File(filePath);
		if(file.isDirectory()){
			for(File f : file.listFiles()){
				if(f.isDirectory()){
					downLoadImg(f.getPath());
				}else if(f.isFile() && f.getName().endsWith(".html")){
					Document doccss = Jsoup.parse(f,"utf-8");
					Elements elinks = doccss.getElementsByTag("img");
					for(Element elink : elinks){
						String imghref = elink.attr("src");
						if(imghref == null || "".equals(imghref)){
							continue;
						}
						if(imghref.indexOf("http://") != -1 || imghref.indexOf("https://") != -1){
							continue;
						}
						if(imghref.indexOf("?") != -1){
							imghref = imghref.substring(0, imghref.indexOf("?"));
						}
						if(imghref.indexOf("#") != -1){
							imghref = imghref.substring(0, imghref.indexOf("#"));
						}
						if(imghref == null || "".equals(imghref)){
							continue;
						}
						int backCount = StringUtils.countMatches(imghref, "../");
						//if(backCount > 0){
						//	System.out.println(111);
						//}
						File rf = new File(f.getPath());
						for(int i=0;i<backCount;i++){
							imghref = imghref.replace("../", "");
							if(rf != null){
								rf = rf.getParentFile();
							}
						}
						if(rf.getParent() != null)
							imghref = rf.getParent().replace("\\", "/") + "/" + imghref;
						
						File jf = new File(imghref);
						String jfp = jf.getParent().replace("\\", "/");
						String jfn = jf.getName();
						downLoadFiles(jfp, jfn);
					}
					//data-src或者data-original为图片延迟加载时使用
					for(Element elink : elinks){
						String imghref = elink.attr("data-src");
						if(imghref == null || "".equals(imghref)){
							continue;
						}
						if(imghref.indexOf("http://") != -1 || imghref.indexOf("https://") != -1){
							continue;
						}
						if(imghref.indexOf("?") != -1){
							imghref = imghref.substring(0, imghref.indexOf("?"));
						}
						if(imghref.indexOf("#") != -1){
							imghref = imghref.substring(0, imghref.indexOf("#"));
						}
						if(imghref == null || "".equals(imghref)){
							continue;
						}
						int backCount = StringUtils.countMatches(imghref, "../");
						//if(backCount > 0){
						//	System.out.println(111);
						//}
						File rf = new File(f.getPath());
						for(int i=0;i<backCount;i++){
							imghref = imghref.replace("../", "");
							if(rf != null){
								rf = rf.getParentFile();
							}
						}
						if(rf.getParent() != null)
							imghref = rf.getParent().replace("\\", "/") + "/" + imghref;
						
						File jf = new File(imghref);
						String jfp = jf.getParent().replace("\\", "/");
						String jfn = jf.getName();
						downLoadFiles(jfp, jfn);
					}
					for(Element elink : elinks){
						String imghref = elink.attr("data-original");
						if(imghref == null || "".equals(imghref)){
							continue;
						}
						if(imghref.indexOf("http://") != -1 || imghref.indexOf("https://") != -1){
							continue;
						}
						if(imghref.indexOf("?") != -1){
							imghref = imghref.substring(0, imghref.indexOf("?"));
						}
						if(imghref.indexOf("#") != -1){
							imghref = imghref.substring(0, imghref.indexOf("#"));
						}
						if(imghref == null || "".equals(imghref)){
							continue;
						}
						int backCount = StringUtils.countMatches(imghref, "../");
						//if(backCount > 0){
						//	System.out.println(111);
						//}
						File rf = new File(f.getPath());
						for(int i=0;i<backCount;i++){
							imghref = imghref.replace("../", "");
							if(rf != null){
								rf = rf.getParentFile();
							}
						}
						if(rf.getParent() != null)
							imghref = rf.getParent().replace("\\", "/") + "/" + imghref;
						
						File jf = new File(imghref);
						String jfp = jf.getParent().replace("\\", "/");
						String jfn = jf.getName();
						downLoadFiles(jfp, jfn);
					}
				}
			}
		}else if(file.isFile()){
			//直接解析
		}
	}
	
	//递归本地css，下载css里import的css、背景图片、字体
	public void downLoadCssImgFonts(String filePath) throws IOException{
		File file = new File(filePath);
		if(file.isDirectory()){
			for(File f : file.listFiles()){
				if(f.isDirectory()){
					downLoadCssImgFonts(f.getPath());
				}else if(f.isFile() && f.getName().endsWith(".css")){
					CSSOMParser cssp = new CSSOMParser(new SACParserCSS3());
					//CSSStyleSheet parseStyleSheet = cssp.parseStyleSheet(new InputSource("file:///F:/eclipse-jee-luna-R-win32-x86_64/workspace/scratch/unify-v1.9.1/" + csshref),null,null);
					InputStreamReader isr = new InputStreamReader(new FileInputStream(f), "utf-8");
					CSSStyleSheet parseStyleSheet = cssp.parseStyleSheet(new InputSource(isr),null,null);
					CSSRuleList cssRules = parseStyleSheet.getCssRules();
					for(int i=0;i<cssRules.getLength();i++){
						CSSRule rule = cssRules.item(i);
						if (rule instanceof CSSStyleRule){
							CSSStyleRule cssrule = (CSSStyleRule) rule;  
							CSSStyleDeclaration styles = cssrule.getStyle();  
							for(int j=0,n=styles.getLength();j<n;j++){  
							    //System.out.println(styles.item(j)+":" + styles.getPropertyValue(styles.item(j)));
								String si = styles.item(j);
								String pv = styles.getPropertyValue(styles.item(j));
							    if(si.indexOf("background") != -1 && pv.indexOf("url(") != -1 && pv.indexOf("data:image") == -1){
							    	System.out.println(pv);
							    	pv = pv.substring(pv.indexOf("url(")+4, pv.indexOf(")",pv.indexOf("url(")));
							    	String imghref = pv;
							    	if(imghref == null || "".equals(imghref)){
										continue;
									}
									if(imghref.indexOf("http://") != -1 || imghref.indexOf("https://") != -1){
										continue;
									}
									if(imghref.indexOf("?") != -1){
										imghref = imghref.substring(0, imghref.indexOf("?"));
									}
									if(imghref.indexOf("#") != -1){
										imghref = imghref.substring(0, imghref.indexOf("#"));
									}
									if(imghref == null || "".equals(imghref)){
										continue;
									}
									int backCount = StringUtils.countMatches(imghref, "../");
									//if(backCount > 0){
									//	System.out.println(111);
									//}
									File rf = new File(f.getPath());
									for(int k=0;k<backCount;k++){
										imghref = imghref.replace("../", "");
										if(rf != null){
											rf = rf.getParentFile();
										}
									}
									if(rf.getParent() != null)
										imghref = rf.getParent().replace("\\", "/") + "/" + imghref;
									
									File jf = new File(imghref);
									String jfp = jf.getParent().replace("\\", "/");
									String jfn = jf.getName();
									downLoadFiles(jfp, jfn);
							    }
							}  
						}else if(rule instanceof CSSImportRule){
							CSSImportRule cssrule = (CSSImportRule) rule;    
							String ichref = cssrule.getHref();
							if(ichref == null || "".equals(ichref)){
								continue;
							}
							if(ichref.indexOf("http://") != -1 || ichref.indexOf("https://") != -1){
								continue;
							}
							if(ichref.indexOf("?") != -1){
								ichref = ichref.substring(0, ichref.indexOf("?"));
							}
							if(ichref.indexOf("#") != -1){
								ichref = ichref.substring(0, ichref.indexOf("#"));
							}
							if(ichref == null || "".equals(ichref)){
								continue;
							}
							int backCount = StringUtils.countMatches(ichref, "../");
							//if(backCount > 0){
							//	System.out.println(111);
							//}
							File rf = new File(f.getPath());
							for(int k=0;k<backCount;k++){
								ichref = ichref.replace("../", "");
								if(rf != null){
									rf = rf.getParentFile();
								}
							}
							if(rf.getParent() != null)
								ichref = rf.getParent().replace("\\", "/") + "/" + ichref;
							
							File jf = new File(ichref);
							String jfp = jf.getParent().replace("\\", "/");
							String jfn = jf.getName();
							downLoadFiles(jfp, jfn);
						//下载字体
						}else if(rule instanceof CSSFontFaceRule){
							CSSFontFaceRule cssrule = (CSSFontFaceRule) rule;    
							CSSStyleDeclaration styles = cssrule.getStyle();  
							for(int j=0,n=styles.getLength();j<n;j++){  
							    System.out.println(styles.item(j)+":" + styles.getPropertyValue(styles.item(j)));
								String si = styles.item(j);
								String pv = styles.getPropertyValue(styles.item(j));
							    if("src".equals(si) && pv.indexOf("url(") != -1 && pv.indexOf("data:application") == -1){
							    	String[] split = pv.split(",");
									for(String s : split){
										String imghref = s.substring(s.indexOf("url(")+4, s.indexOf(")",s.indexOf("url(")));
										if(imghref == null || "".equals(imghref)){
											continue;
										}
										if(imghref.indexOf("http://") != -1 || imghref.indexOf("https://") != -1){
											continue;
										}
										if(imghref.indexOf("?") != -1){
											imghref = imghref.substring(0, imghref.indexOf("?"));
										}
										if(imghref.indexOf("#") != -1){
											imghref = imghref.substring(0, imghref.indexOf("#"));
										}
										if(imghref == null || "".equals(imghref)){
											continue;
										}
										int backCount = StringUtils.countMatches(imghref, "../");
										//if(backCount > 0){
										//	System.out.println(111);
										//}
										File rf = new File(f.getPath());
										for(int k=0;k<backCount;k++){
											imghref = imghref.replace("../", "");
											if(rf != null){
												rf = rf.getParentFile();
											}
										}
										if(rf.getParent() != null)
											imghref = rf.getParent().replace("\\", "/") + "/" + imghref;
										
										File jf = new File(imghref);
										String jfp = jf.getParent().replace("\\", "/");
										String jfn = jf.getName();
										downLoadFiles(jfp, jfn);
									}
							    }
							}  
						}
						
					}
				}
			}
		}else if(file.isFile()){
			//直接解析
		}
	}
	
	private void downLoadFiles(String filePath, String fileName) {
		File pfile = new File(filePath);
		if(!pfile.exists()){
			pfile.mkdirs();
		}
		
		File file = new File(filePath + "/" + fileName);
		if(file.exists() && file.isFile() && file.length() > 0){
			return;
		}
		FileOutputStream fos;
		try {
			fos = new FileOutputStream(file);
		} catch (FileNotFoundException e1) {
			System.out.println("==下载文件出错1==，文件路径为" + this.urlPrefix + "/" + filePath + "/" + fileName);
			file.delete();
			return;
		}
		
		String httpurl = this.urlPrefix + (filePath.startsWith("/") ? "" : "/") + filePath + "/" + fileName;
		URL url = null;
		
		/**
		 * 如果请求地址是https:
		 * 1.将网站证书下载下来，以为https://www.uetdsme.com/uetd/index.html例，下载的证书是wwwuetdsmecom.crt，放到C盘根目录即可
		 * 2.将证书导入到当前项目所使用的jdk中，
		 *   打开cmd，换到C:\Java\jdk1.7.0_75\jre\lib\security目录；
		 *   然后执行keytool -import -v -trustcacerts -alias wwwuetdsmecom -file C:/wwwuetdsmecom.crt -storepass changeit -keystore C:/Java/jdk1.7.0_75/jre/lib/security/cacerts
		 *   选择信任当前证书，会提示“证书已添加到密钥库中”
		 * 3.URLConnection改为HttpsURLConnection
		 *   HttpsURLConnection  con = null;
		 *   con = (HttpsURLConnection)url.openConnection();
		 */
		
		URLConnection con = null;
		//HttpsURLConnection con = null;
		try {
			url = new URL(httpurl);
			con = url.openConnection();
			//con = (HttpsURLConnection)url.openConnection();
			con.setConnectTimeout(60000);
			con.setReadTimeout(60000);
		} catch (MalformedURLException e) {
			System.out.println("==下载文件出错2==，文件路径为" + this.urlPrefix + "/" + filePath + "/" + fileName);
			try {
				fos.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			file.delete();
			return;
		} catch (IOException e) {
			System.out.println("==下载文件出错3==，文件路径为" + this.urlPrefix + "/" + filePath + "/" + fileName);
			try {
				fos.close();
			} catch (IOException e1) {
				e1.printStackTrace();
			}
			file.delete();
			return;
		}
		//System.out.println("    正在下载" + httpurl + "，文件类型为" + con.getContentType() + "，内容编码为" + con.getContentEncoding());
		try{
			InputStream inputStream = null;
			if("gzip".equals(con.getContentEncoding())){
				inputStream = new GZIPInputStream(con.getInputStream());
			}else{
				inputStream = con.getInputStream();
			}
	
			byte[] buffer = new byte[1024];
			int byteread = 0;
			while ((byteread = inputStream.read(buffer)) != -1) {  
				fos.write(buffer, 0, byteread);  
			}
			
			fos.close();
		}catch(Exception e){
			System.out.println("==下载文件出错4==，文件路径为" + this.urlPrefix + "/" + filePath + "/" + fileName);
			e.printStackTrace();
		}
			
	}
}
